1. Objetivo: Explorar e aplicar os conhecimentos obtidos nas aulas expostas sobre Análise exploratória de dados com a linguagem R.

II)Parte 1

Exercicío 1

library(readr)
library(janitor)
library(ggplot2)

caminho <- paste0("C:/Users/monal/Downloads/Curso Ciencias de Dados/us_change.rda")

dados <- load(caminho)

us_change <- janitor::clean_names(us_change) %>% 
  tibble::as_tibble()

#ver o começo do DataSet
head(us_change)

#verdetalhes do Dataset
str(us_change)
tibble [198 x 6] (S3: tbl_df/tbl/data.frame)
 $ quarter     : yearquarter[1:198], format: "1970-01-01" "1970-04-01" ...
 $ consumption : num [1:198] 0.619 0.452 0.873 -0.272 1.901 ...
 $ income      : num [1:198] 1.04 1.23 1.59 -0.24 1.98 ...
 $ production  : num [1:198] -2.452 -0.551 -0.359 -2.186 1.91 ...
 $ savings     : num [1:198] 5.3 7.79 7.4 1.17 3.54 ...
 $ unemployment: num [1:198] 0.9 0.5 0.5 0.7 -0.1 ...
 - attr(*, "key")= tibble [1 x 1] (S3: tbl_df/tbl/data.frame)
  ..$ .rows:List of 1
  .. ..$ : int [1:198] 1 2 3 4 5 6 7 8 9 10 ...
 - attr(*, "index")= chr "Quarter"
  ..- attr(*, "ordered")= logi TRUE
 - attr(*, "index2")= chr "Quarter"
 - attr(*, "interval")=List of 12
  ..$ year       : num 0
  ..$ quarter    : num 1
  ..$ month      : num 0
  ..$ week       : num 0
  ..$ day        : num 0
  ..$ hour       : num 0
  ..$ minute     : num 0
  ..$ second     : num 0
  ..$ millisecond: num 0
  ..$ microsecond: num 0
  ..$ nanosecond : num 0
  ..$ unit       : num 0
  ..- attr(*, "class")= chr "interval"
#primeiro tem que filtrar em dois: 1 para maior que 2000 e 2 para menor que 2000

data_filter_1 <- us_change %>%
  dplyr::select("quarter","unemployment") %>% 
  dplyr::filter(quarter >= "2000-01-01")

data_filter_2 <- us_change %>% 
  dplyr::select("quarter","unemployment") %>% 
  dplyr::filter(quarter < "2000-01-01")

#transformar o primeiro
data.nivel1 <- data_filter_1

data.nivel1$unemployment[1] <-  100; 
for(i in 2:length(data.nivel1$unemployment)){
  data.nivel1$unemployment[i] <-  (1 + data_filter_1$unemployment[i]/100) * data.nivel1$unemployment[i-1]
}

#salvar o primeiro valor
start <- data.nivel1$unemployment[1]

#transformar o segundo
data.nivel2 <- data_filter_2

data.nivel2$unemployment[1] <- (1 + data.nivel2$unemployment[1]/100)* start
for(i in 2:length(data.nivel2$unemployment)){
  data.nivel2$unemployment[i] <-  (1 + data_filter_2$unemployment[i]/100) * data.nivel2$unemployment[i-1]
}

#Agora juntando os datas set
data <- data.nivel2 %>% 
  dplyr::full_join(data.nivel1) %>% 
  tibble::as_tibble()
Joining, by = c("quarter", "unemployment")

Letra B


correl <-  cor(us_change %>% 
      select(-"quarter")) %>% round(2) 

print(correl)
             consumption income production savings unemployment
consumption         1.00   0.38       0.53   -0.26        -0.53
income              0.38   1.00       0.27    0.72        -0.22
production          0.53   0.27       1.00   -0.06        -0.77
savings            -0.26   0.72      -0.06    1.00         0.11
unemployment       -0.53  -0.22      -0.77    0.11         1.00
corrplot::corrplot(correl, 
                   type = "upper",
                   tl.col = "black",
                   )

correl1 <- cor(us_change_nivel %>% dplyr::select(-"quarter")) %>% round(2)

print(correl1)
             consumption income production savings unemployment
consumption         1.00   0.38       0.53   -0.26        -0.03
income              0.38   1.00       0.27    0.72        -0.07
production          0.53   0.27       1.00   -0.06        -0.07
savings            -0.26   0.72      -0.06    1.00        -0.01
unemployment       -0.03  -0.07      -0.07   -0.01         1.00
corrplot::corrplot(correl1, 
                   type = "upper",
                   tl.col = "black",
                   )

Sim, apresentam diferenças porque no primeiro temos o valor “unemployment” em taxa de variação e os outros dados em números, “atrapalhando” a correlação entre os valores e alterando a análise. No segundo, temos todas as colunas na mesma unidade, logo a análise fica confiável.

Letra C


grafico_data <- data %>% 
  ggplot(aes(x = quarter, y = unemployment)) +
  geom_line() +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Evolução do desemprego",
       y = "Quantidade",
       x = "Anos",
       colour = "quarter",
       caption = "Gapminder")

  plotly::ggplotly(grafico_data)

NA

#Gráfico 1


grafico_data1 <- data %>% 
  dplyr::filter(unemployment == max(unemployment)) %>% 
  ggplot(aes(x = quarter, y = unemployment)) +
  geom_point() +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Maior taxa de desemprego",
       y = "Quantidade",
       x = "Anos",
       colour = "quarter",
       caption = "Gapminder")
  
  plotly::ggplotly(grafico_data1)

NA
NA

#Gráfico 2


grafico_data2 <- data %>% 
  ggplot(aes(x = unemployment)) +
  geom_histogram() +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Evolução do Numero de Indice de desemprego",
       y = "Quantidade",
       x = "Número Indice",
       colour = "quarter",
       caption = "Gapminder")
  
  plotly::ggplotly(grafico_data2)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

#Gráfico 3


grafico_data3 <- us_change %>% 
  ggplot(aes(x = quarter, y=unemployment)) +
  geom_line() +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Evolução da Taxa de desemprego",
       y = "Quantidade",
       x = "Anos",
       colour = "quarter",
       caption = "Gapminder")
  
  plotly::ggplotly(grafico_data3)

NA

Letra D

Observando os gráficos é possível visualizar a alta variação existe ao longo dos anos. Observa-se que houve uma máxima taxa de desemprego no gráfico 4, em outubro. Existe uma grande taxa de variação como demonstra o gráfico de variação. Bem como também tem-se grande variação no número índice. No histograma tem-se a quantidade de desemprego por número índice ao longo dos anos.

Letra E

Sim, várias mudanças brucas ao longo do tempo. Temos o periodo de 1980 até 2000, onde o indice de desemprego foi maior registrado e próximo do ano 2000 tem-se o menor índice.

Exercício 2

Letra A - O cuidado adicional inserido na importação do arquivo Retail.xlsx foi o (ship=1) para pular uma linha,porque a planilha do Excel possui duas linhas de cabeçalho.


dados_2 <- readxl::read_excel(path = "C:/Users/monal/Downloads/Curso Ciencias de Dados/retail.xlsx",skip=1) %>% 
  janitor::clean_names() %>%
  tibble::as_tibble()

Letra B - Para transformar o tipo POSIXct na coluna Series_id utilizou-se a biblioteca “lubridate” com a função (as.date())


dados_2 <- dados_2 %>% 
  dplyr::mutate(
    series_id = lubridate::as_date(series_id)
  )

Letra C e D - Essa questão foram feitas juntas de forma a observar a sazonalidade e a têndencia bem como também o outlier ou padrões anômalos. Decompondo pela série utilizando o método X11, observou-se datas especificas de picos de vendas analisada no data set importado.

  
dados2.ts <- dados_2 %>% 
  dplyr::select(c("a3349335t")) %>% 
  ts(
    start = c(
      lubridate::year(dplyr::first(dados_2$series_id)),
      lubridate::month(dplyr::first(dados_2$series_id))),
    
    end = c(
      lubridate::year(dplyr::last(dados_2$series_id)), 
      lubridate::month(dplyr::last(dados_2$series_id))),
    
    frequency = 12
  ) %>% 
  .[,1]

grafico_1 <- autoplot(dados2.ts) + ggtitle("A3349335T") + 
  theme(plot.title = element_text(hjust = 0.5)) + 
  xlab("Anos") +
  ylab("Total de vendas por Dolar$'000s")
  
grafico_2 <- ggseasonplot(dados2.ts, year.labels=TRUE, year.labels.left=TRUE) +
  theme(plot.title = element_text(hjust = 0.5)) +  
  ylab("Total de vendas em dolar$'000s por Ano") +
  ggtitle("Evolução por estação : A3349335T")
  
grafico_3 <- ggmonthplot(dados2.ts) +
  theme(plot.title = element_text(hjust = 0.5)) + 
  ylab("Total de vendas em dolar$'000s") +
  ggtitle("Evolução por Mês: A3349335T")
    
dados2ts2 <- window(dados2.ts, start=1982)
'start' value not changed
grafico_4 <- gglagplot(dados2ts2) + 
  ggtitle("Venda mensal") +
  theme(plot.title = element_text(hjust = 0.5))
  

decomposicao <- stl(dados2.ts, s.window = "periodic", robust = TRUE)  %>%
  pluck("time.series") %>% 
  as_tibble() %>% 
  mutate(
    date = seq(from = lubridate::as_date(dplyr::first(dados_2$series_id)),
               to = lubridate::as_date(dplyr::last(dados_2$series_id)),
               by = "months")
  ) %>% 
  pivot_longer(
    cols = -"date",
    names_to = "decomposition",
    values_to = "valores"
  )
 
  
grafico_5 <- decomposicao %>% 
  filter(decomposition == "seasonal") %>% 
  ggplot(aes(x = date, y = valores)) + 
  theme(plot.title = element_text(hjust = 0.5)) +
  geom_line()+ 
  labs(title = "Sazonalidade",
       y = "Quantidade",
       x = "Anos",
       caption = "Gapminder")

grafico_6 <-  decomposicao %>% 
  filter(decomposition == "trend")  %>% 
  ggplot(aes(x = date, y = valores)) + 
  theme(plot.title = element_text(hjust = 0.5)) +
  geom_line() + 
  labs(title = "Tendência",
       y = "Quantidade",
       x = "Anos",
       caption = "Gapminder")
  
outlier <- dados_2 %>% 
  anomalize::time_decompose("a3349335t") %>%
  anomalize::anomalize(remainder) %>%
  anomalize::time_recompose() %>% 
  dplyr::filter(anomaly == "Yes") %>% 
  dplyr::select(series_id) 
Converting from tbl_df to tbl_time.
Auto-index message: index = series_id
frequency = 12 months
trend = 60 months

#Analise dos Dados

plotly::ggplotly(grafico_1)

#GGseasonplot

plotly::ggplotly(grafico_2)

#ggmonthplot

plotly::ggplotly(grafico_3)

#Exploração dos dados

plotly::ggplotly(grafico_4)
Aspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/widthAspect ratios aren't yet implemented, but you can manually set a suitable height/width

#Sazonalidade

plotly::ggplotly(grafico_5)

#Tendencia

plotly::ggplotly(grafico_6)
outlier
# A time tibble: 8 x 1
# Index: series_id
  series_id 
  <date>    
1 2007-12-01
2 2008-12-01
3 2009-11-01
4 2009-12-01
5 2010-12-01
6 2011-12-01
7 2012-12-01
8 2013-12-01

Parte - 2

Exercício 1 - Spotify

library(gapminder)
library(tidyverse)
library(janitor)


songs <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-01-21/spotify_songs.csv')
Parsed with column specification:
cols(
  .default = col_double(),
  track_id = col_character(),
  track_name = col_character(),
  track_artist = col_character(),
  track_album_id = col_character(),
  track_album_name = col_character(),
  track_album_release_date = col_character(),
  playlist_name = col_character(),
  playlist_id = col_character(),
  playlist_genre = col_character(),
  playlist_subgenre = col_character()
)
See spec(...) for full column specifications.
songs<- songs %>% 
  janitor::clean_names() %>% 
  tibble::as_tibble()


#Analisando dos dados

data_songs_artist <- songs %>% 
  dplyr::select("energy","track_popularity","track_artist","track_album_release_date")


grafic_1 <- data_songs_artist %>% 
  dplyr::filter(track_popularity > 90) %>% 
  dplyr::filter(track_album_release_date >= "2019-06-01") %>% 
  ggplot(aes(x = track_album_release_date, y = track_popularity)) +
  theme(plot.title = element_text(hjust = 0.5)) +
  geom_point() +
  labs(title = "Popularidade (maior 90) entre os artistas ", 
       subtitle = "Por data",
       y = "Popularidade",
       x = "Data",
       colour = "track_artist",
       caption = "Gapminder")
  

grafic_2 <- data_songs_artist %>% 
  dplyr::filter(track_popularity > 90) %>% 
  dplyr::filter(energy > 0.7) %>% 
  ggplot(aes(x = energy, y=track_popularity)) +
  theme(plot.title = element_text(hjust = 0.5)) +
  geom_line() +
  labs(title = "Popularidade (maior 90) entre os artistas ", 
       subtitle = "Por energia (maior 0.7)",
       y = "Popularidade",
       x = "Energy",
       colour = "track_artist",
       caption = "Gapminder")
  
grafic_3 <- data_songs_artist %>% 
  dplyr::filter(energy == max(energy)) %>% 
  ggplot(aes(x = track_popularity, y = energy)) +
  theme(plot.title = element_text(hjust = 0.5)) +
  geom_point() +
  labs(title = "Maior Energy ", 
       subtitle = "Por energia",
       y = "Energy",
       x = "Popularidade",
       colour = "track_artist",
       caption = "Gapminder")
  
grafic_4 <- data_songs_artist %>% 
  ggplot() +
  geom_histogram(aes(energy)) +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Quantidade de musica", 
       subtitle = "Por energia",
       y = "Count music",
       x = "Energy",
       caption = "Gapminder")

songs <- songs %>% 
  dplyr::mutate(track_album_release_date = lubridate::as_date(track_album_release_date))
 1886 failed to parse.
  

data_songs <- songs %>% 
  dplyr::select("track_popularity","track_album_release_date",
                "track_album_name")

grafic_5 <- data_songs %>% 
  dplyr::filter(track_popularity > 80) %>% 
  ggplot(aes(x = track_album_release_date, y= track_popularity)) +
  geom_line()+
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Popularidade entre os artistas ", 
       subtitle = "Por data de lançamento",
       y = "Popularidade",
       x = "Data de Lançamento",
       colour = "track_album_name",
       caption = "Gapminder")

#Analise 1- Spotify

plotly::ggplotly(grafic_1)

#Analise 2 -Spotify

plotly::ggplotly(grafic_2)

#Analise 3 -Spotify

plotly::ggplotly(grafic_3)

#Analise 4 -Spotify

plotly::ggplotly(grafic_4)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

#Analise 5 - Spotify

plotly::ggplotly(grafic_5)

Exercício 2 - Video Games

library(tidyverse)
library(lubridate)

#importanto o DataFrame
video_games <- readr::read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-07-30/video_games.csv")
Parsed with column specification:
cols(
  number = col_double(),
  game = col_character(),
  release_date = col_character(),
  price = col_double(),
  owners = col_character(),
  developer = col_character(),
  publisher = col_character(),
  average_playtime = col_double(),
  median_playtime = col_double(),
  metascore = col_double()
)
head(video_games)

video_games <- video_games %>% 
  janitor::clean_names() %>% 
  dplyr::mutate(
    release_date = mdy(release_date)
  )
 1 failed to parse.
data_filter_price <- video_games %>% 
  dplyr::select("release_date","price") %>% 
  dplyr::filter(price < 0.99)

graf_1 <- data_filter_price %>% 
  ggplot() +
  geom_line(aes(x = price, y = release_date)) +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Comparação dos preços dos jogos ", 
       subtitle = "Por data",
       y = "Preço (< 0,99)",
       x = "Ano",
       colour = "price",
       caption = "Gapminder")
 

graf_2 <- data_filter_price %>%
  dplyr::filter(price == max(price)) %>% 
  ggplot() +
  geom_point(aes(x = release_date, y = price)) +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Evolução dos preços dos jogos", 
       subtitle = "Por data",
       y = "Preço (em dolares)",
       x = "Ano",
       caption = "Gapminder")

graf_3 <- data_filter_price %>%
  ggplot() +
  geom_histogram(aes(price)) +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Quantidade de jogos por preço", 
       subtitle = "Por preço (Price < 0.99)",
       x = "Preço (em dolares)",
       y = "Count games",
       caption = "Gapminder")


data_filter_game <- video_games %>% 
  dplyr::select("game","metascore") %>%
  janitor::clean_names() %>% 
  tibble::as_tibble() %>% 
  tidyr::drop_na() 

graf_4 <- data_filter_game %>% 
  ggplot() +
  geom_histogram(aes(metascore)) +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(title = "Metascore", 
       subtitle = "Por game",
       x = "Metascore",
       y = "Count games",
       caption = "Gapminder")

#Análise 1 - Video Games

 plotly::ggplotly(graf_1)

#Análise 2 - Video Games

plotly::ggplotly(graf_2)

#Análise 3 - Video Games

plotly::ggplotly(graf_3)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

#Análise 4 - Video Games

plotly::ggplotly(graf_4)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
LS0tDQp0aXRsZTogIkludHJvZHXDp8OjbyDDoCBDacOqbmNpYSBkZSBEYWRvcyBlIERlY2lzw6NvIg0KYXV0aG9yOiAiTW9uYWxpc2EgQ29uY2Vpw6fDo28gU2lsdmEiDQpkYXRlOiAiNC8xMy8yMDIwIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KSSkgT2JqZXRpdm86DQogIEV4cGxvcmFyIGUgYXBsaWNhciBvcyBjb25oZWNpbWVudG9zIG9idGlkb3MgbmFzIGF1bGFzIGV4cG9zdGFzIHNvYnJlIEFuw6FsaXNlIGV4cGxvcmF0w7NyaWEgZGUgZGFkb3MgY29tIGEgbGluZ3VhZ2VtIFIuDQogIA0KSUkpUGFydGUgMSANCg0KRXhlcmNpY8OtbyAxDQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KGdncGxvdDIpDQoNCmNhbWluaG8gPC0gcGFzdGUwKCJDOi9Vc2Vycy9tb25hbC9Eb3dubG9hZHMvQ3Vyc28gQ2llbmNpYXMgZGUgRGFkb3MvdXNfY2hhbmdlLnJkYSIpDQoNCmRhZG9zIDwtIGxvYWQoY2FtaW5obykNCg0KdXNfY2hhbmdlIDwtIGphbml0b3I6OmNsZWFuX25hbWVzKHVzX2NoYW5nZSkgJT4lIA0KICB0aWJibGU6OmFzX3RpYmJsZSgpDQoNCiN2ZXIgbyBjb21lw6dvIGRvIERhdGFTZXQNCmhlYWQodXNfY2hhbmdlKQ0KDQojdmVyZGV0YWxoZXMgZG8gRGF0YXNldA0Kc3RyKHVzX2NoYW5nZSkNCg0KI3ByaW1laXJvIHRlbSBxdWUgZmlsdHJhciBlbSBkb2lzOiAxIHBhcmEgbWFpb3IgcXVlIDIwMDAgZSAyIHBhcmEgbWVub3IgcXVlIDIwMDANCg0KZGF0YV9maWx0ZXJfMSA8LSB1c19jaGFuZ2UgJT4lDQogIGRwbHlyOjpzZWxlY3QoInF1YXJ0ZXIiLCJ1bmVtcGxveW1lbnQiKSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIocXVhcnRlciA+PSAiMjAwMC0wMS0wMSIpDQoNCmRhdGFfZmlsdGVyXzIgPC0gdXNfY2hhbmdlICU+JSANCiAgZHBseXI6OnNlbGVjdCgicXVhcnRlciIsInVuZW1wbG95bWVudCIpICU+JSANCiAgZHBseXI6OmZpbHRlcihxdWFydGVyIDwgIjIwMDAtMDEtMDEiKQ0KDQojdHJhbnNmb3JtYXIgbyBwcmltZWlybw0KZGF0YS5uaXZlbDEgPC0gZGF0YV9maWx0ZXJfMQ0KDQpkYXRhLm5pdmVsMSR1bmVtcGxveW1lbnRbMV0gPC0gIDEwMDsgDQpmb3IoaSBpbiAyOmxlbmd0aChkYXRhLm5pdmVsMSR1bmVtcGxveW1lbnQpKXsNCiAgZGF0YS5uaXZlbDEkdW5lbXBsb3ltZW50W2ldIDwtICAoMSArIGRhdGFfZmlsdGVyXzEkdW5lbXBsb3ltZW50W2ldLzEwMCkgKiBkYXRhLm5pdmVsMSR1bmVtcGxveW1lbnRbaS0xXQ0KfQ0KDQojc2FsdmFyIG8gcHJpbWVpcm8gdmFsb3INCnN0YXJ0IDwtIGRhdGEubml2ZWwxJHVuZW1wbG95bWVudFsxXQ0KDQojdHJhbnNmb3JtYXIgbyBzZWd1bmRvDQpkYXRhLm5pdmVsMiA8LSBkYXRhX2ZpbHRlcl8yDQoNCmRhdGEubml2ZWwyJHVuZW1wbG95bWVudFsxXSA8LSAoMSArIGRhdGEubml2ZWwyJHVuZW1wbG95bWVudFsxXS8xMDApKiBzdGFydA0KZm9yKGkgaW4gMjpsZW5ndGgoZGF0YS5uaXZlbDIkdW5lbXBsb3ltZW50KSl7DQogIGRhdGEubml2ZWwyJHVuZW1wbG95bWVudFtpXSA8LSAgKDEgKyBkYXRhX2ZpbHRlcl8yJHVuZW1wbG95bWVudFtpXS8xMDApICogZGF0YS5uaXZlbDIkdW5lbXBsb3ltZW50W2ktMV0NCn0NCg0KI0Fnb3JhIGp1bnRhbmRvIG9zIGRhdGFzIHNldA0KZGF0YSA8LSBkYXRhLm5pdmVsMiAlPiUgDQogIGRwbHlyOjpmdWxsX2pvaW4oZGF0YS5uaXZlbDEpICU+JSANCiAgdGliYmxlOjphc190aWJibGUoKQ0KDQojQWdvcmEgY3JpYW5kbyB1bSBub3ZvIGRhdGFzZXQgY29tIGEgZGF0YSBhcyBjb2x1bmFzIG5vdmFzDQp1c19jaGFuZ2Vfbml2ZWwgPC0gdXNfY2hhbmdlICU+JSANCiAgZHBseXI6Om11dGF0ZShxdWFydGVyID0gZGF0YSRxdWFydGVyLA0KICAgICAgICAgICAgICAgIHVuZW1wbG95bWVudCA9IGRhdGEkdW5lbXBsb3ltZW50KQ0KDQpgYGANCg0KTGV0cmEgQg0KYGBge3J9DQoNCmNvcnJlbCA8LSAgY29yKHVzX2NoYW5nZSAlPiUgDQogICAgICBzZWxlY3QoLSJxdWFydGVyIikpICU+JSByb3VuZCgyKSANCg0KcHJpbnQoY29ycmVsKQ0KDQpjb3JycGxvdDo6Y29ycnBsb3QoY29ycmVsLCANCiAgICAgICAgICAgICAgICAgICB0eXBlID0gInVwcGVyIiwNCiAgICAgICAgICAgICAgICAgICB0bC5jb2wgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgICkNCmBgYA0KYGBge3J9DQpjb3JyZWwxIDwtIGNvcih1c19jaGFuZ2Vfbml2ZWwgJT4lIGRwbHlyOjpzZWxlY3QoLSJxdWFydGVyIikpICU+JSByb3VuZCgyKQ0KDQpwcmludChjb3JyZWwxKQ0KDQpjb3JycGxvdDo6Y29ycnBsb3QoY29ycmVsMSwgDQogICAgICAgICAgICAgICAgICAgdHlwZSA9ICJ1cHBlciIsDQogICAgICAgICAgICAgICAgICAgdGwuY29sID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICApDQoNCmBgYA0KDQpTaW0sIGFwcmVzZW50YW0gZGlmZXJlbsOnYXMgcG9ycXVlIG5vIHByaW1laXJvIHRlbW9zIG8gdmFsb3IgInVuZW1wbG95bWVudCIgZW0gdGF4YSBkZSB2YXJpYcOnw6NvIGUgb3Mgb3V0cm9zIGRhZG9zIGVtIG7Dum1lcm9zLCAiYXRyYXBhbGhhbmRvIiBhIGNvcnJlbGHDp8OjbyBlbnRyZSBvcyB2YWxvcmVzIGUgYWx0ZXJhbmRvIGEgYW7DoWxpc2UuIE5vIHNlZ3VuZG8sIHRlbW9zIHRvZGFzIGFzIGNvbHVuYXMgbmEgbWVzbWEgdW5pZGFkZSwgbG9nbyBhIGFuw6FsaXNlIGZpY2EgY29uZmnDoXZlbC4NCg0KTGV0cmEgQw0KYGBge3J9DQoNCmdyYWZpY29fZGF0YSA8LSBkYXRhICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcXVhcnRlciwgeSA9IHVuZW1wbG95bWVudCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBsYWJzKHRpdGxlID0gIkV2b2x1w6fDo28gZG8gZGVzZW1wcmVnbyIsDQogICAgICAgeSA9ICJRdWFudGlkYWRlIiwNCiAgICAgICB4ID0gIkFub3MiLA0KICAgICAgIGNvbG91ciA9ICJxdWFydGVyIiwNCiAgICAgICBjYXB0aW9uID0gIkdhcG1pbmRlciIpDQoNCiAgcGxvdGx5OjpnZ3Bsb3RseShncmFmaWNvX2RhdGEpDQoNCmBgYA0KDQoNCg0KDQojR3LDoWZpY28gMSANCmBgYHtyfQ0KDQpncmFmaWNvX2RhdGExIDwtIGRhdGEgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKHVuZW1wbG95bWVudCA9PSBtYXgodW5lbXBsb3ltZW50KSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBxdWFydGVyLCB5ID0gdW5lbXBsb3ltZW50KSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBsYWJzKHRpdGxlID0gIk1haW9yIHRheGEgZGUgZGVzZW1wcmVnbyIsDQogICAgICAgeSA9ICJRdWFudGlkYWRlIiwNCiAgICAgICB4ID0gIkFub3MiLA0KICAgICAgIGNvbG91ciA9ICJxdWFydGVyIiwNCiAgICAgICBjYXB0aW9uID0gIkdhcG1pbmRlciIpDQogIA0KICBwbG90bHk6OmdncGxvdGx5KGdyYWZpY29fZGF0YTEpDQoNCg0KYGBgDQoNCg0KDQojR3LDoWZpY28gMg0KYGBge3J9DQpncmFmaWNvX2RhdGEyIDwtIGRhdGEgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB1bmVtcGxveW1lbnQpKSArDQogIGdlb21faGlzdG9ncmFtKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBsYWJzKHRpdGxlID0gIkV2b2x1w6fDo28gZG8gTnVtZXJvIGRlIEluZGljZSBkZSBkZXNlbXByZWdvIiwNCiAgICAgICB5ID0gIlF1YW50aWRhZGUiLA0KICAgICAgIHggPSAiTsO6bWVybyBJbmRpY2UiLA0KICAgICAgIGNvbG91ciA9ICJxdWFydGVyIiwNCiAgICAgICBjYXB0aW9uID0gIkdhcG1pbmRlciIpDQogIA0KICBwbG90bHk6OmdncGxvdGx5KGdyYWZpY29fZGF0YTIpDQoNCmBgYA0KDQoNCiNHcsOhZmljbyAzDQpgYGB7cn0NCg0KZ3JhZmljb19kYXRhMyA8LSB1c19jaGFuZ2UgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBxdWFydGVyLCB5PXVuZW1wbG95bWVudCkpICsNCiAgZ2VvbV9saW5lKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBsYWJzKHRpdGxlID0gIkV2b2x1w6fDo28gZGEgVGF4YSBkZSBkZXNlbXByZWdvIiwNCiAgICAgICB5ID0gIlF1YW50aWRhZGUiLA0KICAgICAgIHggPSAiQW5vcyIsDQogICAgICAgY29sb3VyID0gInF1YXJ0ZXIiLA0KICAgICAgIGNhcHRpb24gPSAiR2FwbWluZGVyIikNCiAgDQogIHBsb3RseTo6Z2dwbG90bHkoZ3JhZmljb19kYXRhMykNCg0KYGBgDQoNCg0KTGV0cmEgRA0KDQpPYnNlcnZhbmRvIG9zIGdyw6FmaWNvcyDDqSBwb3Nzw612ZWwgdmlzdWFsaXphciBhIGFsdGEgdmFyaWHDp8OjbyBleGlzdGUgYW8gbG9uZ28gZG9zIGFub3MuIA0KT2JzZXJ2YS1zZSBxdWUgaG91dmUgdW1hIG3DoXhpbWEgdGF4YSBkZSBkZXNlbXByZWdvIG5vIGdyw6FmaWNvIDQsIGVtIG91dHVicm8uDQpFeGlzdGUgdW1hIGdyYW5kZSB0YXhhIGRlIHZhcmlhw6fDo28gY29tbyBkZW1vbnN0cmEgbyBncsOhZmljbyBkZSB2YXJpYcOnw6NvLiBCZW0gY29tbyB0YW1iw6ltIHRlbS1zZSBncmFuZGUgdmFyaWHDp8OjbyBubyBuw7ptZXJvIMOtbmRpY2UuDQpObyBoaXN0b2dyYW1hIHRlbS1zZSBhIHF1YW50aWRhZGUgZGUgZGVzZW1wcmVnbyBwb3IgbsO6bWVybyDDrW5kaWNlIGFvIGxvbmdvIGRvcyBhbm9zLg0KDQpMZXRyYSBFDQoNClNpbSwgdsOhcmlhcyBtdWRhbsOnYXMgYnJ1Y2FzIGFvIGxvbmdvIGRvIHRlbXBvLiBUZW1vcyBvIHBlcmlvZG8gZGUgMTk4MCBhdMOpIDIwMDAsIG9uZGUgbyBpbmRpY2UgZGUgZGVzZW1wcmVnbyBmb2kgbWFpb3IgcmVnaXN0cmFkbyBlIHByw7N4aW1vIGRvIGFubyAyMDAwIHRlbS1zZSBvIG1lbm9yIMOtbmRpY2UuDQoNCg0KRXhlcmPDrWNpbyAyDQoNCkxldHJhIEEgLSBPIGN1aWRhZG8gYWRpY2lvbmFsIGluc2VyaWRvIG5hIGltcG9ydGHDp8OjbyBkbyBhcnF1aXZvIFJldGFpbC54bHN4IGZvaSBvIChzaGlwPTEpIHBhcmEgcHVsYXIgdW1hIGxpbmhhLHBvcnF1ZSBhIHBsYW5pbGhhIGRvIEV4Y2VsIHBvc3N1aSBkdWFzIGxpbmhhcyBkZSBjYWJlw6dhbGhvLg0KDQpgYGB7cn0NCg0KZGFkb3NfMiA8LSByZWFkeGw6OnJlYWRfZXhjZWwocGF0aCA9ICJDOi9Vc2Vycy9tb25hbC9Eb3dubG9hZHMvQ3Vyc28gQ2llbmNpYXMgZGUgRGFkb3MvcmV0YWlsLnhsc3giLHNraXA9MSkgJT4lIA0KICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpICU+JQ0KICB0aWJibGU6OmFzX3RpYmJsZSgpDQoNCg0KYGBgDQoNCkxldHJhIEIgLSBQYXJhIHRyYW5zZm9ybWFyIG8gdGlwbyBQT1NJWGN0IG5hIGNvbHVuYSBTZXJpZXNfaWQgdXRpbGl6b3Utc2UgYSBiaWJsaW90ZWNhICJsdWJyaWRhdGUiIGNvbSBhIGZ1bsOnw6NvIChhcy5kYXRlKCkpDQpgYGB7cn0NCg0KZGFkb3NfMiA8LSBkYWRvc18yICU+JSANCiAgZHBseXI6Om11dGF0ZSgNCiAgICBzZXJpZXNfaWQgPSBsdWJyaWRhdGU6OmFzX2RhdGUoc2VyaWVzX2lkKQ0KICApDQoNCmBgYA0KDQpMZXRyYSBDIGUgRCAtICBFc3NhIHF1ZXN0w6NvIGZvcmFtIGZlaXRhcyBqdW50YXMgZGUgZm9ybWEgYSBvYnNlcnZhciBhIHNhem9uYWxpZGFkZSBlIGEgdMOqbmRlbmNpYSBiZW0gY29tbyB0YW1iw6ltIG8gb3V0bGllciBvdSBwYWRyw7VlcyBhbsO0bWFsb3MuIERlY29tcG9uZG8gcGVsYSBzw6lyaWUgdXRpbGl6YW5kbyBvIG3DqXRvZG8gWDExLCBvYnNlcnZvdS1zZSBkYXRhcyBlc3BlY2lmaWNhcyBkZSBwaWNvcyBkZSB2ZW5kYXMgYW5hbGlzYWRhIG5vIGRhdGEgc2V0IGltcG9ydGFkby4NCg0KYGBge3J9DQogIA0KZGFkb3MyLnRzIDwtIGRhZG9zXzIgJT4lIA0KICBkcGx5cjo6c2VsZWN0KGMoImEzMzQ5MzM1dCIpKSAlPiUgDQogIHRzKA0KICAgIHN0YXJ0ID0gYygNCiAgICAgIGx1YnJpZGF0ZTo6eWVhcihkcGx5cjo6Zmlyc3QoZGFkb3NfMiRzZXJpZXNfaWQpKSwNCiAgICAgIGx1YnJpZGF0ZTo6bW9udGgoZHBseXI6OmZpcnN0KGRhZG9zXzIkc2VyaWVzX2lkKSkpLA0KICAgIA0KICAgIGVuZCA9IGMoDQogICAgICBsdWJyaWRhdGU6OnllYXIoZHBseXI6Omxhc3QoZGFkb3NfMiRzZXJpZXNfaWQpKSwgDQogICAgICBsdWJyaWRhdGU6Om1vbnRoKGRwbHlyOjpsYXN0KGRhZG9zXzIkc2VyaWVzX2lkKSkpLA0KICAgIA0KICAgIGZyZXF1ZW5jeSA9IDEyDQogICkgJT4lIA0KICAuWywxXQ0KDQpncmFmaWNvXzEgPC0gYXV0b3Bsb3QoZGFkb3MyLnRzKSArIGdndGl0bGUoIkEzMzQ5MzM1VCIpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArIA0KICB4bGFiKCJBbm9zIikgKw0KICB5bGFiKCJUb3RhbCBkZSB2ZW5kYXMgcG9yIERvbGFyJCcwMDBzIikNCiAgDQpncmFmaWNvXzIgPC0gZ2dzZWFzb25wbG90KGRhZG9zMi50cywgeWVhci5sYWJlbHM9VFJVRSwgeWVhci5sYWJlbHMubGVmdD1UUlVFKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArICANCiAgeWxhYigiVG90YWwgZGUgdmVuZGFzIGVtIGRvbGFyJCcwMDBzIHBvciBBbm8iKSArDQogIGdndGl0bGUoIkV2b2x1w6fDo28gcG9yIGVzdGHDp8OjbyA6IEEzMzQ5MzM1VCIpDQogIA0KZ3JhZmljb18zIDwtIGdnbW9udGhwbG90KGRhZG9zMi50cykgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyANCiAgeWxhYigiVG90YWwgZGUgdmVuZGFzIGVtIGRvbGFyJCcwMDBzIikgKw0KICBnZ3RpdGxlKCJFdm9sdcOnw6NvIHBvciBNw6pzOiBBMzM0OTMzNVQiKQ0KICAgIA0KZGFkb3MydHMyIDwtIHdpbmRvdyhkYWRvczIudHMsIHN0YXJ0PTE5ODIpDQoNCmdyYWZpY29fNCA8LSBnZ2xhZ3Bsb3QoZGFkb3MydHMyKSArIA0KICBnZ3RpdGxlKCJWZW5kYSBtZW5zYWwiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KICANCg0KZGVjb21wb3NpY2FvIDwtIHN0bChkYWRvczIudHMsIHMud2luZG93ID0gInBlcmlvZGljIiwgcm9idXN0ID0gVFJVRSkgICU+JQ0KICBwbHVjaygidGltZS5zZXJpZXMiKSAlPiUgDQogIGFzX3RpYmJsZSgpICU+JSANCiAgbXV0YXRlKA0KICAgIGRhdGUgPSBzZXEoZnJvbSA9IGx1YnJpZGF0ZTo6YXNfZGF0ZShkcGx5cjo6Zmlyc3QoZGFkb3NfMiRzZXJpZXNfaWQpKSwNCiAgICAgICAgICAgICAgIHRvID0gbHVicmlkYXRlOjphc19kYXRlKGRwbHlyOjpsYXN0KGRhZG9zXzIkc2VyaWVzX2lkKSksDQogICAgICAgICAgICAgICBieSA9ICJtb250aHMiKQ0KICApICU+JSANCiAgcGl2b3RfbG9uZ2VyKA0KICAgIGNvbHMgPSAtImRhdGUiLA0KICAgIG5hbWVzX3RvID0gImRlY29tcG9zaXRpb24iLA0KICAgIHZhbHVlc190byA9ICJ2YWxvcmVzIg0KICApDQogDQogIA0KZ3JhZmljb181IDwtIGRlY29tcG9zaWNhbyAlPiUgDQogIGZpbHRlcihkZWNvbXBvc2l0aW9uID09ICJzZWFzb25hbCIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHZhbG9yZXMpKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBnZW9tX2xpbmUoKSsgDQogIGxhYnModGl0bGUgPSAiU2F6b25hbGlkYWRlIiwNCiAgICAgICB5ID0gIlF1YW50aWRhZGUiLA0KICAgICAgIHggPSAiQW5vcyIsDQogICAgICAgY2FwdGlvbiA9ICJHYXBtaW5kZXIiKQ0KDQpncmFmaWNvXzYgPC0gIGRlY29tcG9zaWNhbyAlPiUgDQogIGZpbHRlcihkZWNvbXBvc2l0aW9uID09ICJ0cmVuZCIpICAlPiUgDQogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB2YWxvcmVzKSkgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsNCiAgZ2VvbV9saW5lKCkgKyANCiAgbGFicyh0aXRsZSA9ICJUZW5kw6puY2lhIiwNCiAgICAgICB5ID0gIlF1YW50aWRhZGUiLA0KICAgICAgIHggPSAiQW5vcyIsDQogICAgICAgY2FwdGlvbiA9ICJHYXBtaW5kZXIiKQ0KICANCm91dGxpZXIgPC0gZGFkb3NfMiAlPiUgDQogIGFub21hbGl6ZTo6dGltZV9kZWNvbXBvc2UoImEzMzQ5MzM1dCIpICU+JQ0KICBhbm9tYWxpemU6OmFub21hbGl6ZShyZW1haW5kZXIpICU+JQ0KICBhbm9tYWxpemU6OnRpbWVfcmVjb21wb3NlKCkgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKGFub21hbHkgPT0gIlllcyIpICU+JSANCiAgZHBseXI6OnNlbGVjdChzZXJpZXNfaWQpIA0KDQpgYGANCg0KDQojQW5hbGlzZSBkb3MgRGFkb3MNCmBgYHtyfQ0KcGxvdGx5OjpnZ3Bsb3RseShncmFmaWNvXzEpDQpgYGANCiNHR3NlYXNvbnBsb3QNCmBgYHtyfQ0KcGxvdGx5OjpnZ3Bsb3RseShncmFmaWNvXzIpDQpgYGANCiNnZ21vbnRocGxvdA0KYGBge3J9DQpwbG90bHk6OmdncGxvdGx5KGdyYWZpY29fMykNCmBgYA0KI0V4cGxvcmHDp8OjbyBkb3MgZGFkb3MNCmBgYHtyfQ0KcGxvdGx5OjpnZ3Bsb3RseShncmFmaWNvXzQpDQpgYGANCiNTYXpvbmFsaWRhZGUNCmBgYHtyfQ0KcGxvdGx5OjpnZ3Bsb3RseShncmFmaWNvXzUpDQpgYGANCiNUZW5kZW5jaWENCmBgYHtyfQ0KcGxvdGx5OjpnZ3Bsb3RseShncmFmaWNvXzYpDQpgYGANCg0KYGBge3J9DQpvdXRsaWVyDQpgYGANCg0KDQpQYXJ0ZSAtIDINCg0KRXhlcmPDrWNpbyAxIC0gU3BvdGlmeQ0KYGBge3J9DQpsaWJyYXJ5KGdhcG1pbmRlcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShqYW5pdG9yKQ0KDQoNCnNvbmdzIDwtIHJlYWRyOjpyZWFkX2NzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDIwLzIwMjAtMDEtMjEvc3BvdGlmeV9zb25ncy5jc3YnKQ0KDQpzb25nczwtIHNvbmdzICU+JSANCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogIHRpYmJsZTo6YXNfdGliYmxlKCkNCg0KDQojQW5hbGlzYW5kbyBkb3MgZGFkb3MNCg0KZGF0YV9zb25nc19hcnRpc3QgPC0gc29uZ3MgJT4lIA0KICBkcGx5cjo6c2VsZWN0KCJlbmVyZ3kiLCJ0cmFja19wb3B1bGFyaXR5IiwidHJhY2tfYXJ0aXN0IiwidHJhY2tfYWxidW1fcmVsZWFzZV9kYXRlIikNCg0KDQpncmFmaWNfMSA8LSBkYXRhX3NvbmdzX2FydGlzdCAlPiUgDQogIGRwbHlyOjpmaWx0ZXIodHJhY2tfcG9wdWxhcml0eSA+IDkwKSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIodHJhY2tfYWxidW1fcmVsZWFzZV9kYXRlID49ICIyMDE5LTA2LTAxIikgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB0cmFja19hbGJ1bV9yZWxlYXNlX2RhdGUsIHkgPSB0cmFja19wb3B1bGFyaXR5KSkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBsYWJzKHRpdGxlID0gIlBvcHVsYXJpZGFkZSAobWFpb3IgOTApIGVudHJlIG9zIGFydGlzdGFzICIsIA0KICAgICAgIHN1YnRpdGxlID0gIlBvciBkYXRhIiwNCiAgICAgICB5ID0gIlBvcHVsYXJpZGFkZSIsDQogICAgICAgeCA9ICJEYXRhIiwNCiAgICAgICBjb2xvdXIgPSAidHJhY2tfYXJ0aXN0IiwNCiAgICAgICBjYXB0aW9uID0gIkdhcG1pbmRlciIpDQogIA0KDQpncmFmaWNfMiA8LSBkYXRhX3NvbmdzX2FydGlzdCAlPiUgDQogIGRwbHlyOjpmaWx0ZXIodHJhY2tfcG9wdWxhcml0eSA+IDkwKSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoZW5lcmd5ID4gMC43KSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGVuZXJneSwgeT10cmFja19wb3B1bGFyaXR5KSkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGxhYnModGl0bGUgPSAiUG9wdWxhcmlkYWRlIChtYWlvciA5MCkgZW50cmUgb3MgYXJ0aXN0YXMgIiwgDQogICAgICAgc3VidGl0bGUgPSAiUG9yIGVuZXJnaWEgKG1haW9yIDAuNykiLA0KICAgICAgIHkgPSAiUG9wdWxhcmlkYWRlIiwNCiAgICAgICB4ID0gIkVuZXJneSIsDQogICAgICAgY29sb3VyID0gInRyYWNrX2FydGlzdCIsDQogICAgICAgY2FwdGlvbiA9ICJHYXBtaW5kZXIiKQ0KICANCmdyYWZpY18zIDwtIGRhdGFfc29uZ3NfYXJ0aXN0ICU+JSANCiAgZHBseXI6OmZpbHRlcihlbmVyZ3kgPT0gbWF4KGVuZXJneSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gdHJhY2tfcG9wdWxhcml0eSwgeSA9IGVuZXJneSkpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgbGFicyh0aXRsZSA9ICJNYWlvciBFbmVyZ3kgIiwgDQogICAgICAgc3VidGl0bGUgPSAiUG9yIGVuZXJnaWEiLA0KICAgICAgIHkgPSAiRW5lcmd5IiwNCiAgICAgICB4ID0gIlBvcHVsYXJpZGFkZSIsDQogICAgICAgY29sb3VyID0gInRyYWNrX2FydGlzdCIsDQogICAgICAgY2FwdGlvbiA9ICJHYXBtaW5kZXIiKQ0KICANCmdyYWZpY180IDwtIGRhdGFfc29uZ3NfYXJ0aXN0ICU+JSANCiAgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoZW5lcmd5KSkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBsYWJzKHRpdGxlID0gIlF1YW50aWRhZGUgZGUgbXVzaWNhIiwgDQogICAgICAgc3VidGl0bGUgPSAiUG9yIGVuZXJnaWEiLA0KICAgICAgIHkgPSAiQ291bnQgbXVzaWMiLA0KICAgICAgIHggPSAiRW5lcmd5IiwNCiAgICAgICBjYXB0aW9uID0gIkdhcG1pbmRlciIpDQoNCnNvbmdzIDwtIHNvbmdzICU+JSANCiAgZHBseXI6Om11dGF0ZSh0cmFja19hbGJ1bV9yZWxlYXNlX2RhdGUgPSBsdWJyaWRhdGU6OmFzX2RhdGUodHJhY2tfYWxidW1fcmVsZWFzZV9kYXRlKSkNCiAgDQoNCmRhdGFfc29uZ3MgPC0gc29uZ3MgJT4lIA0KICBkcGx5cjo6c2VsZWN0KCJ0cmFja19wb3B1bGFyaXR5IiwidHJhY2tfYWxidW1fcmVsZWFzZV9kYXRlIiwNCiAgICAgICAgICAgICAgICAidHJhY2tfYWxidW1fbmFtZSIpDQoNCmdyYWZpY181IDwtIGRhdGFfc29uZ3MgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKHRyYWNrX3BvcHVsYXJpdHkgPiA4MCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB0cmFja19hbGJ1bV9yZWxlYXNlX2RhdGUsIHk9IHRyYWNrX3BvcHVsYXJpdHkpKSArDQogIGdlb21fbGluZSgpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKw0KICBsYWJzKHRpdGxlID0gIlBvcHVsYXJpZGFkZSBlbnRyZSBvcyBhcnRpc3RhcyAiLCANCiAgICAgICBzdWJ0aXRsZSA9ICJQb3IgZGF0YSBkZSBsYW7Dp2FtZW50byIsDQogICAgICAgeSA9ICJQb3B1bGFyaWRhZGUiLA0KICAgICAgIHggPSAiRGF0YSBkZSBMYW7Dp2FtZW50byIsDQogICAgICAgY29sb3VyID0gInRyYWNrX2FsYnVtX25hbWUiLA0KICAgICAgIGNhcHRpb24gPSAiR2FwbWluZGVyIikNCg0KYGBgDQoNCiNBbmFsaXNlIDEtIFNwb3RpZnkNCmBgYHtyfQ0KcGxvdGx5OjpnZ3Bsb3RseShncmFmaWNfMSkNCmBgYA0KDQojQW5hbGlzZSAyIC1TcG90aWZ5DQpgYGB7cn0NCnBsb3RseTo6Z2dwbG90bHkoZ3JhZmljXzIpDQpgYGANCg0KI0FuYWxpc2UgMyAtU3BvdGlmeQ0KYGBge3J9DQpwbG90bHk6OmdncGxvdGx5KGdyYWZpY18zKQ0KYGBgDQojQW5hbGlzZSA0IC1TcG90aWZ5DQpgYGB7cn0NCnBsb3RseTo6Z2dwbG90bHkoZ3JhZmljXzQpDQpgYGANCiNBbmFsaXNlIDUgLSBTcG90aWZ5DQpgYGB7cn0NCnBsb3RseTo6Z2dwbG90bHkoZ3JhZmljXzUpDQpgYGANCg0KDQpFeGVyY8OtY2lvIDIgLSBWaWRlbyBHYW1lcw0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KDQojaW1wb3J0YW50byBvIERhdGFGcmFtZQ0KdmlkZW9fZ2FtZXMgPC0gcmVhZHI6OnJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L21hc3Rlci9kYXRhLzIwMTkvMjAxOS0wNy0zMC92aWRlb19nYW1lcy5jc3YiKQ0KDQpoZWFkKHZpZGVvX2dhbWVzKQ0KDQp2aWRlb19nYW1lcyA8LSB2aWRlb19nYW1lcyAlPiUgDQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgJT4lIA0KICBkcGx5cjo6bXV0YXRlKA0KICAgIHJlbGVhc2VfZGF0ZSA9IG1keShyZWxlYXNlX2RhdGUpDQogICkNCg0KDQpkYXRhX2ZpbHRlcl9wcmljZSA8LSB2aWRlb19nYW1lcyAlPiUgDQogIGRwbHlyOjpzZWxlY3QoInJlbGVhc2VfZGF0ZSIsInByaWNlIikgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKHByaWNlIDwgMC45OSkNCg0KZ3JhZl8xIDwtIGRhdGFfZmlsdGVyX3ByaWNlICU+JSANCiAgZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBwcmljZSwgeSA9IHJlbGVhc2VfZGF0ZSkpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsNCiAgbGFicyh0aXRsZSA9ICJDb21wYXJhw6fDo28gZG9zIHByZcOnb3MgZG9zIGpvZ29zICIsIA0KICAgICAgIHN1YnRpdGxlID0gIlBvciBkYXRhIiwNCiAgICAgICB5ID0gIlByZcOnbyAoPCAwLDk5KSIsDQogICAgICAgeCA9ICJBbm8iLA0KICAgICAgIGNvbG91ciA9ICJwcmljZSIsDQogICAgICAgY2FwdGlvbiA9ICJHYXBtaW5kZXIiKQ0KIA0KDQpncmFmXzIgPC0gZGF0YV9maWx0ZXJfcHJpY2UgJT4lDQogIGRwbHlyOjpmaWx0ZXIocHJpY2UgPT0gbWF4KHByaWNlKSkgJT4lIA0KICBnZ3Bsb3QoKSArDQogIGdlb21fcG9pbnQoYWVzKHggPSByZWxlYXNlX2RhdGUsIHkgPSBwcmljZSkpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsNCiAgbGFicyh0aXRsZSA9ICJFdm9sdcOnw6NvIGRvcyBwcmXDp29zIGRvcyBqb2dvcyIsIA0KICAgICAgIHN1YnRpdGxlID0gIlBvciBkYXRhIiwNCiAgICAgICB5ID0gIlByZcOnbyAoZW0gZG9sYXJlcykiLA0KICAgICAgIHggPSAiQW5vIiwNCiAgICAgICBjYXB0aW9uID0gIkdhcG1pbmRlciIpDQoNCmdyYWZfMyA8LSBkYXRhX2ZpbHRlcl9wcmljZSAlPiUNCiAgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMocHJpY2UpKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArDQogIGxhYnModGl0bGUgPSAiUXVhbnRpZGFkZSBkZSBqb2dvcyBwb3IgcHJlw6dvIiwgDQogICAgICAgc3VidGl0bGUgPSAiUG9yIHByZcOnbyAoUHJpY2UgPCAwLjk5KSIsDQogICAgICAgeCA9ICJQcmXDp28gKGVtIGRvbGFyZXMpIiwNCiAgICAgICB5ID0gIkNvdW50IGdhbWVzIiwNCiAgICAgICBjYXB0aW9uID0gIkdhcG1pbmRlciIpDQoNCg0KZGF0YV9maWx0ZXJfZ2FtZSA8LSB2aWRlb19nYW1lcyAlPiUgDQogIGRwbHlyOjpzZWxlY3QoImdhbWUiLCJtZXRhc2NvcmUiKSAlPiUNCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogIHRpYmJsZTo6YXNfdGliYmxlKCkgJT4lIA0KICB0aWR5cjo6ZHJvcF9uYSgpIA0KDQpncmFmXzQgPC0gZGF0YV9maWx0ZXJfZ2FtZSAlPiUgDQogIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKG1ldGFzY29yZSkpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsNCiAgbGFicyh0aXRsZSA9ICJNZXRhc2NvcmUiLCANCiAgICAgICBzdWJ0aXRsZSA9ICJQb3IgZ2FtZSIsDQogICAgICAgeCA9ICJNZXRhc2NvcmUiLA0KICAgICAgIHkgPSAiQ291bnQgZ2FtZXMiLA0KICAgICAgIGNhcHRpb24gPSAiR2FwbWluZGVyIikNCg0KYGBgDQoNCiNBbsOhbGlzZSAxIC0gVmlkZW8gR2FtZXMNCmBgYHtyfQ0KIHBsb3RseTo6Z2dwbG90bHkoZ3JhZl8xKQ0KYGBgDQojQW7DoWxpc2UgMiAtIFZpZGVvIEdhbWVzDQpgYGB7cn0NCnBsb3RseTo6Z2dwbG90bHkoZ3JhZl8yKQ0KYGBgDQojQW7DoWxpc2UgMyAtIFZpZGVvIEdhbWVzDQpgYGB7cn0NCnBsb3RseTo6Z2dwbG90bHkoZ3JhZl8zKQ0KYGBgDQojQW7DoWxpc2UgNCAtIFZpZGVvIEdhbWVzDQpgYGB7cn0NCnBsb3RseTo6Z2dwbG90bHkoZ3JhZl80KQ0KYGBgDQoNCg==